#if !IN_LOCAL
#define ReportToStdErr(...) __VA_ARGS__
#endif // !IN_LOCAL
#include<iostream>
#include<utility>
using namespace std;
using ull = unsigned long long;
constexpr const int Minf = -2147483647 / 2;
constexpr const unsigned mod = 1000000007, modM2 = mod - 2, modM1 = mod - 1;
inline constexpr unsigned Power(unsigned a, unsigned b)
{
	unsigned ans = 1;
	for (; b; a = static_cast<ull>(a) * a % mod, b /= 2)
	{
		if (b % 2)
		{
			ans = ans * static_cast<ull>(a) % mod;
		}
	}
	return ans;
}
inline constexpr unsigned Inv(const unsigned val)
{
	return Power(val, modM2);
}
inline constexpr void UpdateMax(unsigned& pos, const unsigned val)
{
	if (pos < val)
	{
		pos = val;
	}
	return;
}
class BarrettReduction
{
	using ull = unsigned long long; unsigned mod, a, b;
public:
	constexpr BarrettReduction() :mod(), a(), b() {}
	constexpr BarrettReduction(const unsigned _mod) : mod(), a(), b() { Load(_mod); }
	inline constexpr void Load(const unsigned _mod) { mod = _mod; const ull val = (~static_cast<ull>(mod - 1)) / mod + 1; a = val >> 32; b = static_cast<unsigned>(val); return; }
	inline constexpr unsigned operator()(const unsigned val)const
	{
		const ull t = static_cast<ull>(val) * a; return val - (((((static_cast<ull>(val) * b) >> 32) + (t & 0xffffffff)) >> 32) + (t >> 32)) * mod;
	}
	inline constexpr unsigned operator()(const ull val)const
	{
		const ull t1 = (val & 0xffffffffu) * a, t2 = (val >> 32) * b;
		return static_cast<unsigned>(val - ((((((val & 0xffffffffu) * b) >> 32) + (t1 & 0xffffffff) + (t2 & 0xffffffff)) >> 32) + (t1 >> 32) + (t2 >> 32) + (val >> 32) * a) * mod);
	}
	inline constexpr unsigned operator[](const unsigned val)const { const unsigned ans = operator()(val); return ans >= mod ? ans - mod : ans; }
	inline constexpr unsigned operator[](const ull val)const { const unsigned ans = operator()(val); return ans >= mod ? ans - mod : ans; }
	inline constexpr unsigned UnderflowReduce(const unsigned val)const { return static_cast<int>(val) < 0 ? val + mod : val; }
}br_m;
char buffer[33554432];
const char* p_buf_in = buffer;
inline unsigned ReadU()
{
	for (; *p_buf_in < '0'; ++p_buf_in);
	unsigned ans = *p_buf_in ^ '0';
	for (; *(++p_buf_in) >= '0'; ans = ans * 10 + *p_buf_in - '0');
	return ans;
}
constexpr const size_t N = 1500051;
bool is_irrelevant[N], is_forbidden[N];
int mM3;
unsigned mM1, mP1, farthest_node, tree_depth, root, rootM1, dis_left_mod_m, irrelevant_node, siz_chosen_color, p_pre, edg[N], father[N], diam[N], depth[N], height[N], cate[N], chosen_color[N], pre[N];
pair<unsigned, unsigned> diam_dis;
struct Edge
{
	unsigned dest, next;
}edg_info[3000003];
constexpr unsigned& pre_0 = pre[0];
inline void Link(const unsigned from, const unsigned to)
{
	static unsigned edge_count = 0;
	edg_info[++edge_count].next = edg[from];
	edg_info[edg[from] = edge_count].dest = to;
	return;
}
inline void DFS1(const unsigned pos, const unsigned father, const unsigned depth)
{
	if (depth > tree_depth)
	{
		tree_depth = depth;
		farthest_node = pos;
	}
	for (unsigned i = edg[pos]; i; i = edg_info[i].next)
	{
		if (edg_info[i].dest != father)
		{
			DFS1(edg_info[i].dest, pos, depth + 1);
		}
	}
	return;
}
inline void DFS2(const unsigned pos, const unsigned depth)
{
	if (depth > tree_depth)
	{
		tree_depth = depth;
		farthest_node = pos;
	}
	for (unsigned i = edg[pos]; i; i = edg_info[i].next)
	{
		if (father[edg_info[i].dest] == 0)
		{
			father[edg_info[i].dest] = pos;
			DFS2(edg_info[i].dest, depth + 1);
		}
	}
	return;
}
inline void DFS3(const unsigned pos, const unsigned father)
{
	cate[pos] = root;
	for (unsigned i = edg[pos]; i; i = edg_info[i].next)
	{
		if (edg_info[i].dest != father)
		{
			depth[edg_info[i].dest] = depth[pos] + 1;
			DFS3(edg_info[i].dest, pos);
			UpdateMax(height[pos], height[edg_info[i].dest] + 1);
		}
	}
	if (depth[pos] + diam_dis.first + height[pos] < mM1)
	{
		++irrelevant_node;
		is_irrelevant[pos] = 1;
	}
	else if (depth[pos] + diam_dis.second + height[pos] >= mM1)
	{
		const unsigned color_1 = br_m[depth[pos] + dis_left_mod_m], color_2 = br_m.UnderflowReduce(dis_left_mod_m - br_m[depth[pos]]);
		if (color_1 != color_2)
		{
			is_forbidden[color_1] = is_forbidden[color_2] = 1;
		}
	}
	return;
}
inline void Process()
{
	const unsigned diam_rootM1 = diam[root - 1], diam_root = diam[root], diam_rootP1 = diam[root + 1];
	for (unsigned i = edg[diam_root]; i; i = edg_info[i].next)
	{
		if (edg_info[i].dest != diam_rootM1 && edg_info[i].dest != diam_rootP1)
		{
			depth[edg_info[i].dest] = 1;
			DFS3(edg_info[i].dest, diam_root);
		}
	}
	return;
}
inline unsigned Calc(const unsigned pos, const unsigned father, const unsigned remain_depth)
{
	if (is_irrelevant[pos] || remain_depth == 0)
	{
		return 1;
	}
	unsigned ans = 1;
	for (unsigned i = edg[pos]; i; i = edg_info[i].next)
	{
		if (edg_info[i].dest != father)
		{
			ans = ans * static_cast<ull>(Calc(edg_info[i].dest, pos, remain_depth - 1)) % mod;
		}
	}
	return ans + 1;
}
inline void DFS4(const unsigned pos, const unsigned father)
{
	const unsigned dis_l = depth[pos] + diam_dis.first, dis_r = depth[pos] + diam_dis.second, maxi_dis_l = dis_l + height[pos], maxi_dis_r = dis_r + height[pos];
	if (maxi_dis_l < mM1)
	{
		if (maxi_dis_r >= mM1)
		{
			if (dis_r <= mM1)
			{
				const unsigned t = Calc(pos, father, mM1 - dis_r);
				pre[p_pre] = pre[p_pre] * static_cast<ull>(t) % mod;
				pre[rootM1] = static_cast<ull>(pre[rootM1]) * Inv(t) % mod;
				if (p_pre > rootM1)
				{
					pre_0 = pre_0 * static_cast<ull>(t) % mod;
				}
			}
			return;
		}
	}
	else if (maxi_dis_r < mM1)
	{
		if (dis_l <= mM1)
		{
			pre[root] = pre[root] * static_cast<ull>(Calc(pos, father, mM1 - dis_l)) % mod;
		}
		return;
	}
	else
	{
		int maxi_depth = Minf, second_maxi_depth = Minf;
		for (unsigned i = edg[pos]; i; i = edg_info[i].next)
		{
			if (edg_info[i].dest != father)
			{
				if (maxi_depth < static_cast<int>(height[edg_info[i].dest]))
				{
					second_maxi_depth = maxi_depth;
					maxi_depth = height[edg_info[i].dest];
				}
				else if (second_maxi_depth < static_cast<int>(height[edg_info[i].dest]))
				{
					second_maxi_depth = height[edg_info[i].dest];
				}
			}
		}
		if (maxi_depth + second_maxi_depth >= mM3)
		{
			const unsigned v1 = maxi_depth + 2, v2 = second_maxi_depth + 2, t1 = br_m[dis_l];
			for (unsigned i = 1; i <= siz_chosen_color; ++i)
			{
				if (chosen_color[i] != t1)
				{
					const unsigned t2 = br_m.UnderflowReduce(chosen_color[i] - t1);
					is_forbidden[chosen_color[i]] |= ((t2 <= static_cast<unsigned>(second_maxi_depth + 1) && t2 * 2 <= mM1) || min(v1, t2) + min(v2, t2) >= mP1);
				}
			}
		}
	}
	for (unsigned i = edg[pos]; i; i = edg_info[i].next)
	{
		if (edg_info[i].dest != father)
		{
			DFS4(edg_info[i].dest, pos);
		}
	}
	return;
}
int main()
{
    freopen("life.in","r",stdin);
    freopen("life.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cin.read(buffer, 33554432);
	const unsigned n = ReadU(), m = ReadU();
	mM1 = m - 1;
	br_m.Load(m);
	for (unsigned i = 1; i != n; ++i)
	{
		const unsigned a = ReadU(), b = ReadU();
		Link(a, b);
		Link(b, a);
	}
	DFS1(1, 0, 1);
	father[farthest_node] = -1;
	tree_depth = 0;
	DFS2(farthest_node, 1);
	if (tree_depth <= mM1)
	{
		cout << "YES\n" << Power(2, n);
	}
	else
	{
		unsigned siz_diam = 0;
		for (unsigned i = farthest_node;; i = father[i])
		{
			if (father[diam[++siz_diam] = i] == -1)
			{
				break;
			}
		}
		root = 1;
		for (const unsigned limit = siz_diam / 2; root <= limit; diam_dis.first = siz_diam - root, dis_left_mod_m = br_m[diam_dis.second = root - 1], Process(), ++root);
		for (; root <= siz_diam; dis_left_mod_m = br_m[diam_dis.first = root - 1], diam_dis.second = siz_diam - root, Process(), ++root);
		for (unsigned i = 0; i != m; ++i)
		{
			if (!is_forbidden[i])
			{
				chosen_color[++siz_chosen_color] = i;
			}
		}
		if (siz_chosen_color)
		{
			for (unsigned i = 0; i != m; pre[i++] = 1);
			p_pre = br_m[siz_diam];
			mM3 = m - 3;
			mP1 = m + 1;
			for (root = 1; root <= siz_diam; ++root)
			{
				diam_dis.first = root - 1;
				diam_dis.second = siz_diam - root;
				const unsigned diam_rootM1 = diam[rootM1 = root - 1], diam_root = diam[root], diam_rootP1 = diam[root + 1];
				for (unsigned i = edg[diam_root]; i; i = edg_info[i].next)
				{
					if (edg_info[i].dest != diam_rootM1 && edg_info[i].dest != diam_rootP1)
					{
						DFS4(edg_info[i].dest, diam_root);
					}
				}
			}
			bool ans1 = 0;
			ull ans2 = 0;
			for (unsigned i = 0, t = 1; i != m; ++i)
			{
				t = static_cast<ull>(t) * pre[i] % mod;
				if (!is_forbidden[i])
				{
					ans1 = 1;
					ans2 += t;
				}
			}
			if (ans1)
			{
				cout << "YES\n" << (ans2 % mod * Power(2, irrelevant_node) % mod);
			}
			else
			{
				cout << "NO\n0";
			}
		}
		else
		{
			cout << "NO\n0";
		}
	}
	return 0;
}